﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Tradier.Models;
using Newtonsoft.Json.Linq;
using RestSharp;
using System.Globalization;

namespace Tradier
{
    public partial class UserPositions : System.Web.UI.Page
    {
        public Dictionary<int, List<PositionModel>> Positions { get; set; }

        protected void Page_Load(object sender, EventArgs e)
        {
            var accessToken = Session["UserTradierAccessToken"];
            if (accessToken == null)
            {
                Response.Redirect("/login.aspx");
            }
            GetUserOrders((string)accessToken);
        }

        private void GetUserOrders(string accessToken)
        {
            try
            {
                var client = new RestClient("https://api.tradier.com");
                var request = new RestRequest("/v1/user/positions", Method.GET);

                request.AddHeader("Authorization", "Bearer " + accessToken);
                var result = (client.Execute(request).Content);
                var json = JObject.Parse(result);

                Positions = CreateMapping(json);
                if (Positions.Count > 0)
                {
                    var quotes = GetQuotes();
                    MapQuote(quotes);
                }
            }
            catch
            {

            }
        }

        private Dictionary<int, List<PositionModel>> CreateMapping(JObject json)
        {
            var positionModel = new Dictionary<int, List<PositionModel>>();
            var accountPositions = new List<PositionModel>();

            var accounts = json["accounts"]["account"];
            if (accounts.GetType().Name == "JArray")
            {
                foreach (JObject account in accounts)
                {
                    accountPositions = new List<PositionModel>();
                    if (account["positions"].HasValues)
                    {
                        var positions = account["positions"]["position"];
                        var accountNumber = (int)account["account_number"];

                        if (positions.GetType().Name == "JArray")
                        {
                            foreach (var positionItem in positions)
                            {
                                var position = new PositionModel()
                                {
                                    CostBasis = (float)positionItem["cost_basis"],
                                    DateAcquired = DateTime.ParseExact((string)positionItem["date_acquired"], "MM/dd/yyyy HH:mm:ss", CultureInfo.InvariantCulture),
                                    Id = (int)positionItem["id"],
                                    Quantity = (int)positionItem["quantity"],
                                    Symbol = (string)positionItem["symbol"],
                                };
                                accountPositions.Add(position);
                            }
                        }
                        else
                        {
                            var positionItem = positions;
                            var position = new PositionModel()
                            {
                                CostBasis = (float)positionItem["cost_basis"],
                                DateAcquired = DateTime.ParseExact((string)positionItem["date_acquired"], "MM/dd/yyyy HH:mm:ss", CultureInfo.InvariantCulture),
                                Id = (int)positionItem["id"],
                                Quantity = (int)positionItem["quantity"],
                                Symbol = (string)positionItem["symbol"],
                            };
                            accountPositions.Add(position);
                        }
                        positionModel.Add(accountNumber, accountPositions);
                    }
                }
            }
            else
            {
                if (accounts["positions"].HasValues)
                {
                    var positions = accounts["positions"]["position"];
                    var accountNumber = (int)accounts["account_number"];
                    accountPositions = new List<PositionModel>();

                    if (positions.GetType().Name == "JArray")
                    {
                        foreach (var positionItem in positions)
                        {
                            var position = new PositionModel()
                            {
                                CostBasis = (float)positionItem["cost_basis"],
                                DateAcquired = DateTime.ParseExact((string)positionItem["date_acquired"], "MM/dd/yyyy HH:mm:ss", CultureInfo.InvariantCulture),
                                Id = (int)positionItem["id"],
                                Quantity = (int)positionItem["quantity"],
                                Symbol = (string)positionItem["symbol"],
                            };
                            accountPositions.Add(position);
                        }
                    }
                    else
                    {
                        var positionItem = positions;
                        string type = (string)positionItem["type"];
                        var position = new PositionModel()
                        {
                            CostBasis = (float)positionItem["cost_basis"],
                            DateAcquired = DateTime.ParseExact((string)positionItem["date_acquired"], "MM/dd/yyyy HH:mm:ss", CultureInfo.InvariantCulture),
                            Id = (int)positionItem["id"],
                            Quantity = (int)positionItem["quantity"],
                            Symbol = (string)positionItem["symbol"],
                        };
                        accountPositions.Add(position);
                    }
                    positionModel.Add(accountNumber, accountPositions);
                }
            }

            return positionModel;
        }

        private Dictionary<string, QuoteModel> GetQuotes()
        {
            List<string> symbols = new List<string>();
            Dictionary<string, QuoteModel> quotesModel = new Dictionary<string, QuoteModel>();

            foreach (var position in Positions.Values)
            {
                symbols.AddRange(position.Select(x => x.Symbol).ToList());
            }
            symbols = symbols.Distinct().ToList();

            string criteria = string.Join(",", symbols);

            var accessToken = (string)Session["UserTradierAccessToken"];

            RestClient client = new RestClient("https://api.tradier.com");
            var request = new RestRequest(string.Format("/v1/markets/quotes?symbols={0}", criteria), Method.GET);
            request.AddHeader("Content-type", "application/json");
            request.AddHeader("Authorization", "Bearer " + accessToken);

            var result = (client.Execute(request).Content);
            var json = JObject.Parse(result);
            if (json.HasValues && json["quotes"].HasValues)
            {
                var quotes = json["quotes"]["quote"];
                if (quotes.GetType().Name == "JArray")
                {
                    foreach (var quote in quotes)
                    {
                        var quoteItem = new QuoteModel()
                        {
                            Symbol = quote["symbol"] != null ? (string)quote["symbol"] : "",
                            Description = quote["description"] != null ? (string)quote["description"] : "",
                            Exch = quote["exch"] != null ? (string)quote["exch"] : "",
                            Type = quote["type"] != null ? (string)quote["type"] : "",
                            Last = !string.IsNullOrEmpty(quote["last"].ToString()) ? (float)quote["last"] : 0,
                            Change = !string.IsNullOrEmpty(quote["change"].ToString()) ? (float)quote["change"] : 0,
                            ChangePercentage = !string.IsNullOrEmpty(quote["change_percentage"].ToString()) ? (float)quote["change_percentage"] : 0,
                            Volume = !string.IsNullOrEmpty(quote["volume"].ToString()) ? (int)quote["volume"] : 0,
                            AverageVolume = !string.IsNullOrEmpty(quote["average_volume"].ToString()) ? (int)quote["average_volume"] : 0,
                            LastVolume = !string.IsNullOrEmpty(quote["last_volume"].ToString()) ? (int)quote["last_volume"] : 0,
                            TradeDate = !string.IsNullOrEmpty(quote["trade_date"].ToString()) ? (long)quote["trade_date"] : 0,
                            Open = !string.IsNullOrEmpty(quote["open"].ToString()) ? (float)quote["open"] : 0,
                            High = !string.IsNullOrEmpty(quote["high"].ToString()) ? (float)quote["high"] : 0,
                            Low = !string.IsNullOrEmpty(quote["low"].ToString()) ? (float)quote["low"] : 0,
                            Close = !string.IsNullOrEmpty(quote["close"].ToString()) ? (float)quote["close"] : 0,
                            PrevClose = !string.IsNullOrEmpty(quote["prevclose"].ToString()) ? (float)quote["prevclose"] : 0,
                            Week52High = !string.IsNullOrEmpty(quote["week_52_high"].ToString()) ? (float)quote["week_52_high"] : 0,
                            Week52Low = !string.IsNullOrEmpty(quote["week_52_low"].ToString()) ? (float)quote["week_52_low"] : 0,
                            Bid = !string.IsNullOrEmpty(quote["bid"].ToString()) ? (float)quote["bid"] : 0,
                            BidSize = !string.IsNullOrEmpty(quote["bidsize"].ToString()) ? (int)quote["bidsize"] : 0,
                            BidExch = !string.IsNullOrEmpty(quote["bidexch"].ToString()) ? (string)quote["bidexch"] : "",
                            BidDate = !string.IsNullOrEmpty(quote["bid_date"].ToString()) ? (long)quote["bid_date"] : 0,
                            Ask = !string.IsNullOrEmpty(quote["ask"].ToString()) ? (float)quote["ask"] : 0,
                            AskSize = !string.IsNullOrEmpty(quote["asksize"].ToString()) ? (int)quote["asksize"] : 0,
                            AskExch = !string.IsNullOrEmpty(quote["askexch"].ToString()) ? (string)quote["askexch"] : "",
                            AskDate = !string.IsNullOrEmpty(quote["ask_date"].ToString()) ? (long)quote["ask_date"] : 0
                        };

                        if (quoteItem.Type == "option")
                        {
                            quoteItem.OpenInterest = quote["open_interest"] != null ? (int)quote["open_interest"] : 0;
                            quoteItem.Underlying = quote["underlying"] != null ? (string)quote["underlying"] : "";
                            quoteItem.Strike = quote["strike"] != null ? (float)quote["strike"] : 0;
                            quoteItem.ContractSize = quote["contract_size"] != null ? (int)quote["contract_size"] : 0;
                            quoteItem.ExpirationDate = quote["expiration_date"] != null ? (string)quote["expiration_date"] : "";
                            quoteItem.ExpirationType = quote["expiration_type"] != null ? (string)quote["expiration_type"] : "";
                            quoteItem.OptionType = quote["option_type"] != null ? (string)quote["option_type"] : "";
                        }

                        quotesModel.Add(quoteItem.Symbol, quoteItem);
                    }
                }
            }
            return quotesModel;
        }

        private void MapQuote(Dictionary<string, QuoteModel> quotes)
        {
            foreach (var accountPosition in Positions.Values)
            {
                foreach (var position in accountPosition)
                {
                    var quote = quotes[position.Symbol];
                    position.Last = quote.Last;
                    position.Value = position.Quantity * position.Last;
                    position.Change = quote.Change;
                    position.Description = quote.Description;
                    position.Type = quote.Type;

                    position.GainLoss = position.Value - position.CostBasis;
                    if (quote.Type == "option")
                    {
                        if( !string.IsNullOrEmpty(position.Description))
                        {
                            var desc = position.Description.Split(' ');
                            position.Symbol = desc[0];
                        }
                        position.Value = position.Value * quote.ContractSize;
                    }
                }
            }
        }
    }
}